<?php
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
/**
 * 公共函数定义文件
 *
 */
if (!function_exists("show")) {
	/**
	 * API接口使用，返回带code,msg,data的json
	 * @author MrGuo
	 * @date   2020-12-19
	 * @param  int|integer $code [返回码 200成功 400及以上失败，不要用0]
	 * @param  string      $msg  [提示信息，必须直观]
	 * @param  [type]      $data [返回数据]
	 * @param  [bool]      $encrypt [是否进行数据加密]
	 * @return [json]      [json]
	 */
	function show(int $code = 200, string $msg = "请求成功", $data = null, $encrypt = false) {
		return response()->json(array("data" => $data, "msg" => $msg, "code" => $code));
	}
	/**
	 * 参数顺序不变，少了第一个code
	 * 不建议在业务判断较强的地方使用，code一样，前端不好处理
	 */
	function show_success(string $msg = "请求成功", $data = null, $encrypt = false) {
		return show(200, $data, $encrypt);
	}
	/**
	 * 参数顺序不变，少了code和encrypt
	 * 不建议在业务判断较强的地方使用，code一样的前端不好处理
	 */
	function show_error(string $msg = "请求异常", $data = null) {
		return show(500, $data);
	}
}

if (!function_exists("unique_no")) {
	/**
	 * 生成唯一订单号
	 * @author MrGuo
	 * @param  string     $prefix  [订单号前缀]
	 * @param  int        $randNum [结尾自定义随机字符串]
	 * @return string              [订单号，默认20位]
	 */
	function unique_no(string $prefix = "", int $randNum = null) {
		$snowId = new \Godruoyi\Snowflake\Snowflake();
		return strtoupper($prefix) . date("Y") . $snowId->id() . ($randNum ?? '');
	}
}
if (!function_exists("unique_bigint")) {
	/**
	 * 生成唯一的Bigint数字ID，分布式系统中使用，每台主机配置不同的datacenter和workerid
	 * @author MrGuo
	 * @date   2020-12-19
	 * @param  int|null   $datacenter [数据中心ID,1-5位]
	 * @param  int|null   $workerid   [机器ID,1-5位]
	 * @param  int|null   $randNum    [自定义随机数，不加默认返回16位]
	 * @return [string]               [唯一ID]
	 */
	function unique_bigint(int $datacenter = null, int $workerid = null, int $randNum = null) {
		$snowId = new \Godruoyi\Snowflake\Snowflake($datacenter, $workerid);
		$snowId->setStartTimeStamp(strtotime(date("Y-01-01 00:00:00")));
		return $snowId->id() . ($randNum ?? '');
	}
}
if (!function_exists("uuid")) {
	/**
	 * Laravel的UUID
	 * @author MrGuo
	 * @date   2020-12-19
	 * @return [string]     [uuid]
	 */
	function uuid() {
		return Str::uuid();
	}
}
if (!function_exists("validate_form")) {
	/**
	 * 表单批量验证
	 * @author MrGuo
	 * @date   2020-12-21
	 * @param  array      $fields 		数组，
	 * @param  bool       $exit 		验证不通过是否直接exit，默认关闭
	 * @demo   validate_form(["mobile|手机号" => "required|size:11","name|姓名" => "required"])
	 * @return string||true           	错误信息，验证通过返回true
	 */
	function validate_form(array $fields = [], bool $exit = false) {
		$rules = [];
		$labels = [];
		$error = false;
		try {
			foreach ($fields as $key => $rule) {
				$arr = explode("|", $key);
				$labels[$arr[0]] = $arr[1] ?? $arr[0];
				$rules[$arr[0]] = $rule;
			}
			$validator = Validator::make(request()->all(), $rules, [], $labels);
			if ($validator->errors()->first()) {
				$error = $validator->errors()->first();
			}
		} catch (\Exception $e) {
			$error = "表单验证规则错误";
		}
		if ($error !== false) {
			if ($exit) {
				echo json_encode(['code' => 600, 'msg' => $error], JSON_UNESCAPED_UNICODE);
				exit;
			}
			return $error;
		}
		return true;
	}
}

if (!function_exists("children_tree")) {
	/**
	 *  递归二叉树
	 * @author MrGuo
	 * @date   2020-12-19
	 * @param  array        $son   [二维数组，主键名是id]
	 * @param  boolean|null $alone [是否返回没有找到上级的, 默认返回]
	 * @return [array]             [N维数组，children是子集，level表示第几级]
	 */
	function children_tree(array $son = [], string $field = "pid", boolean $alone = null) {
		$father = [];
		foreach ($son as $key => $val) {
			if (intval($val[$field]) == 0) {
				//获取第一代
				array_push($father, $val);
				unset($son[$key]);
			}
		}
		foreach ($father as $key => $val) {
			$father[$key] = __Children($val, $son, 0);
		}
		if ($alone) {
			//保留没有父级的孤儿
			foreach ($son as $key => $val) {
				array_push($father, $val);
			}
		}
		return $father;
	}
	function __Children(array $father = [], array $son = [], int $level = 0, string $field = "pid") {
		$father['children'] = array();
		foreach ($son as $k => $v) {
			if (intval($v[$field]) == intval($father['id'])) {
				$sons = __Children($v, $son, $level + 1, $field); //递归，把一个系先全部找完。
				array_push($father['children'], $sons);
				unset($son[$k]);
			}
		}
		$father['level'] = $level;
		return $father;
	}
}
if (!function_exists("select_options")) {
	/**
	 * 通过数据列表快速转换成select2的options选项 ，$id为新键，$field为值
	 * @author MrGuo
	 * @date   2020-12-20
	 * @param  array      $data  [二维数组]
	 * @param  string     $id    [取原数组中的$id新的键]
	 * @param  string     $field [取原数组中的$field为值]
	 * @return array             [二维数组]
	 */
	function select_options(array $data, string $id = "id", string $field = "name") {
		$arr = [];
		foreach ($data as $k => $v) {
			$arr[$v[$id]] = isset($v[$field]) ? $v[$field] : '';
		}
		return $arr;
	}
}
if (!function_exists("check_image_url")) {
	/**
	 * 返回完整图片链接，如果不是http开头的完整链接则会拼接当前文件驱动的主路径
	 * @author MrGuo
	 * @date   2020-12-19
	 * @return [type]            [string]
	 */
	function check_picture_url(string $path) {
		if (stripos(strtolower($path), "http") !== 0) {
			return config("filesystems.disks." . env("FILESYSTEM_DRIVER") . '.url') . $path;
		}
		return $path;
	}
}

if (!function_exists("check_image_array")) {
	/**
	 * 批量替换图片服务器路径
	 * @author MrGuo
	 * @date   2020-12-19
	 * @param  array      $arr   [二维数组]
	 * @param  string     $field [字段名]
	 * @return array             [二维数组]
	 */
	function check_image_array(array $arr = [], string $field = "image") {
		if (!empty($arr)) {
			$url = config("filesystems.disks." . env("FILESYSTEM_DRIVER") . '.url');
			foreach ($arr as $key => $val) {
				if (isset($val[$field]) && gettype($val[$field]) == 'string' && stripos(strtolower($val[$field]), "http") !== 0) {
					$arr[$key][$field] = $url . $val[$field];
				}
			}
		}
		return $arr;
	}
}

if (!function_exists('request_domain')) {
	/**
	 * 当前请求域名
	 * @author MrGuo
	 * @date   2020-12-19
	 * @param  boolean    $port [是否携带端口]
	 * @return string           [带协议的域名 , 80和443会省略]
	 */
	function request_domain(boolean $port = null) {
		$url = $_SERVER['REQUEST_SCHEME'] . "://" . $_SERVER['HTTP_HOST'];
		if (($_SERVER['SERVER_PORT'] != "80" && $_SERVER['SERVER_PORT'] != '443') && $port) {
			$url .= $_SERVER['SERVER_PORT'] . ":" . $_SERVER['SERVER_PORT'];
		}
		return $url;
	}
}
if (!function_exists('curl_post')) {
	/**
	 * [发送curl的POST请求]
	 * @author MrGuo
	 * @date   2020-12-19
	 * @param  string $url    [请求链接]
	 * @param  array  $data   [参数，字符串或者数组]
	 * @param  array  $header [请求Header]
	 * @return [type]         [false表示失败]
	 */
	function curl_post(string $url = '', $data = [], array $header = []) {
		$ch = curl_init();

		// $header=[
		//      'Content-Type:'.'application/x-www-form-urlencoded; charset=UTF-8'
		// ];
		// curl_setopt($ch, CURLOPT_SSLVERSION, 1);//检验SSL
		// if (defined('CURL_SSLVERSION_TLSv1')) {
		//  curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
		// }
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
		if (!empty($header)) {
			curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
			curl_setopt($ch, CURLOPT_HEADER, 0); //返回response头部信息
		}
		curl_setopt($ch, CURLOPT_POST, 1);
		curl_setopt($ch, CURLOPT_POSTFIELDS, gettype($data) == 'string' ? $data : http_build_query($data));
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
		curl_setopt($ch, CURLOPT_TIMEOUT, 30);
		$rs = curl_exec($ch);
		if (curl_errno($ch)) {
			//出错则显示错误信息
			//var_dump( curl_error($ch) );
			return false;
		} else {
			curl_close($ch);
			//默认了进行了json转换
			$arr = json_decode($rs, true);
			if ($arr) {
				return $arr;
			}
			return $rs;
		}
	}
}
if (!function_exists('curl_get')) {
	/**
	 * [发送curl的GET请求]
	 * @author MrGuo
	 * @date   2020-12-19
	 * @param  string $url    [请求链接]
	 * @param  array  $data   [参数, 字符串或者数组]
	 * @param  array  $header [请求Header]
	 * @return [type]         [false表示失败]
	 */
	function curl_get(string $url = '', $data = "", array $header = []) {
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
		if (!empty($header)) {
			curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
			curl_setopt($ch, CURLOPT_HEADER, 0); //返回response头部信息
		}
		if ($data != '') {
			$url .= "?" . (gettype($data) == 'string' ? $data : http_build_query($data));
		}
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
		curl_setopt($ch, CURLOPT_TIMEOUT, 30);
		$rs = curl_exec($ch);
		if (curl_errno($ch)) {
			//出错则显示错误信息
			//var_dump( curl_error($ch) );
			return false;
		} else {
			curl_close($ch);
			//默认了进行了json转换
			$arr = json_decode($rs, true);
			if ($arr) {
				return $arr;
			}
			return $rs;
		}
	}
}

if (!function_exists('admin_config')) {
	/**
	 * 获取系统配置表配置，注意，此方法使用了Cache
	 * @author MrGuo
	 * @date   2020-12-19
	 * @param  string     $key [字段名]
	 * @return [type]          [description]
	 */
	function admin_config(string $key = '') {
		$config = \App\Models\AdminConfig::getConfig($key);
		return $config;
	}
}

if (!function_exists('sys_config_group')) {
	/**
	 * 获取系统配置表配置
	 * @Date   2020-08-07
	 * @param  string     $key [字段名]
	 * @return [type]          [description]
	 */
	function sys_config_group(string $key = '') {
		$config = \App\Models\AdminConfig::getConfigByGroup($key);
		return $config;
	}
}

if (!function_exists('rand_char')) {
	/**
	 * 生成随机字符串
	 * @param int $length 生成长度
	 * @param int $type 生成类型：0-小写字母+数字，1-小写字母，2-大写字母，3-数字，4-小写+大写字母，5-小写+大写+数字
	 * @return string
	 */
	function rand_char($length = 8, $type = 5) {
		$a = 'abcdefghijklmnopqrstuvwxyz';
		$A = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
		$n = '0123456789';

		switch ($type) {
		case 1:$chars = $a;
			break;
		case 2:$chars = $A;
			break;
		case 3:$chars = $n;
			break;
		case 4:$chars = $a . $A;
			break;
		case 5:$chars = $a . $A . $n;
			break;
		default:$chars = $a . $n;
		}

		$str = '';
		for ($i = 0; $i < $length; $i++) {
			$str .= $chars[mt_rand(0, strlen($chars) - 1)];
		}
		return $str;
	}
}

if (!function_exists('format_bytes')) {
	/**
	 * 格式化字节大小
	 * @param  number $size      字节数
	 * @param  string $delimiter 数字和单位分隔符
	 * @return string            格式化后的带单位的大小
	 */
	function format_bytes($size, $delimiter = '') {
		$units = array('B', 'KB', 'MB', 'GB', 'TB', 'PB');
		for ($i = 0; $size >= 1024 && $i < 5; $i++) {
			$size /= 1024;
		}

		return round($size, 2) . $delimiter . $units[$i];
	}
}

if (!function_exists('get_client_ip')) {
	/**
	 * 获取客户端IP地址
	 * @return mixed
	 */
	function get_client_ip() {
		if (isset($_SERVER)) {
			if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
				$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
			} else if (isset($_SERVER['HTTP_CLIENT_IP'])) {
				$ip = $_SERVER['HTTP_CLIENT_IP'];
			} else {
				$ip = $_SERVER['REMOTE_ADDR'];
			}
		} else {
			if (getenv('HTTP_X_FORWARDED_FOR')) {
				$ip = getenv('HTTP_X_FORWARDED_FOR');
			} else if (getenv('HTTP_CLIENT_IP')) {
				$ip = getenv('HTTP_CLIENT_IP');
			} else {
				$ip = getenv('REMOTE_ADDR');
			}
		}
		// IP地址合法验证
		if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) || filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
			return $ip;
		}
		return 'Unknown';
	}
}

/**
 * @param $str 字符串
 * @param $start 替换字符的开始文字
 * @param $len  替换字符的长度
 * @param $symbol 替换的字符  例如*、#等
 * @return string
 */
if (!function_exists("str_replaces")) {
    function str_replaces($str, $start, $len, $symbol = '*')
    {
        $end = $start + $len;
        // 截取头保留的字符
        $str1 = mb_substr($str, 0, $start);
        // 截取尾保留的字符
        $str2 = mb_substr($str, $end);

        //  生产要替换的字符
        $symbol_num = '';
        for ($i = 0; $i < $len; $i++) {
            $symbol_num .= $symbol;
        }
        return $str1 . $symbol_num ;
    }
}

if (!function_exists("aes_encrypt")) {

	/**
	 * aes加密
	 * @author MrGuo
	 * @date   2021-01-09
	 * @param  [type]     $str [需要加密的字符串或数组或对象]
	 * @param  string     $key [description]
	 * @param  string     $iv  [description]
	 * @return [type]          [description]
	 */
	function aes_encrypt($str, string $key, string $iv) {
		if (gettype($str) == "array" || gettype($str) == "object") {
			$str = json_encode($str, JSON_UNESCAPED_UNICODE);
		}
		$encrypted = base64_encode(openssl_encrypt($str, "AES-128-CBC", $key, true, $iv));
		return $encrypted;
	}
	/**
	 * aes解密
	 * @author MrGuo
	 * @date   2021-01-09
	 * @param  string     $data [description]
	 * @param  string     $key  [description]
	 * @param  string     $iv   [description]
	 * @return [type]           [description]
	 */
	function aes_decrypt(string $data, string $key, string $iv) {

		$decrypted = openssl_decrypt(base64_decode($data), "AES-128-CBC", $key, true, $iv);

		if (json_decode($decrypted, true)) {
			return json_decode($decrypted, true);
		} else {
			return $decrypted;
		}
	}
	/* js 解密 代码:
		    import CryptoJS from './cryptojs/crypto-js.js';
		    import Config from '../../config.js';
		    var crypto = {
		      //默认采用 CBC  Pkcs7
		      encrypt:function(str){
		        if(typeof(str)=="object"||typeof(str)=="array"){
		          str=JSON.stringify(str);
		        }else{
		          str=str.toString();
		        }
		        let key=CryptoJS.enc.Utf8.parse(Config.aes_key);
		        let iv=CryptoJS.enc.Utf8.parse(Config.aes_iv);
		        var encrypted = CryptoJS.AES.encrypt(str,key,{
		          iv:iv,
		          mode:CryptoJS.mode.CBC,
		          padding:CryptoJS.pad.Pkcs7,
		        });
		        return encrypted.toString();
		      },
		      decrypt:function(str) {
		        let key=CryptoJS.enc.Utf8.parse(Config.aes_key);
		        let iv=CryptoJS.enc.Utf8.parse(Config.aes_iv);

		        var decrypted = CryptoJS.AES.decrypt(str,key,{
		          iv:iv,
		          padding:CryptoJS.pad.Pkcs7
		        });
		        return decrypted.toString(CryptoJS.enc.Utf8);
		      }

		    }
		    module.exports = crypto;

	*/
    if (!function_exists('rand_name')) {
        function rand_name()
        {
            $code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
            $rand = $code[rand(0,25)]
                .strtoupper(dechex(date('m')))
                .date('d').substr(time(),-5)
                .substr(microtime(),2,5)
                .sprintf('%02d',rand(0,99));
            for(
                $a = md5( $rand, true ),
                $s = '0123456789ABCDEFGHIJKLMNOPQRSTUV',
                $d = '',
                $f = 0;
                $f < 8;
                $g = ord( $a[ $f ] ),
                $d .= $s[ ( $g ^ ord( $a[ $f + 8 ] ) ) - $g & 0x1F ],
                $f++
            );
            return  $d;
        }
    }
    if (! function_exists('now')) {
        /**
         * Create a new Carbon instance for the current time.
         *
         * @param  \DateTimeZone|string|null  $tz
         * @return \Illuminate\Support\Carbon
         */
        function now($tz = null)
        {
            return Date::now($tz);
        }
    }
    if (! function_exists('to_sex_month')) {
        function to_sex_month()
        {
            $arr = array();
            $old_time = strtotime('-5 month', date('Y-m'));
            dd($old_time);
            for ($i = 0; $i <= 6;$i++) {
                $t = strtotime("+$i month", $old_time);
                $arr[] = date('Y/m',$t);
            }
            return $arr;
        }

    }

if (! function_exists('mysubstr')){
    function mysubstr($str, $start, $len)
    {

        $tmpstr = "";

        $strlen = $start + $len;

        for ($i = 0; $i < $strlen; $i++) {

            if (ord(substr($str, $i, 1)) > 0xa0) {

                $tmpstr .= substr($str, $i, 2);

                $i++;

            } else

                $tmpstr .= substr($str, $i, 1);

        }

        return $tmpstr;

    }
}

}